package com.cyberinsight.cps.cybersphere.modelparser.rapidminer.parser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;

import com.cyberinsight.cps.cybersphere.modelparser.rapidminer.exception.ParseException;
import com.cyberinsight.cps.cybersphere.modelparser.rapidminer.reader.IReader;
import com.cyberinsight.cps.cybersphere.modelparser.model.Connection;
import com.cyberinsight.cps.cybersphere.modelparser.model.ProcessDefinition;
import com.rapidminer.Process;
import com.rapidminer.io.process.XMLImporter;
import com.rapidminer.operator.ExecutionUnit;
import com.rapidminer.operator.Operator;
import com.rapidminer.operator.ProcessRootOperator;
import com.rapidminer.operator.ports.OutputPort;
import com.rapidminer.parameter.Parameters;
import com.rapidminer.tools.OperatorService;

/**
 * 使用Rapidminer规范解析文件
 * 
 * @author guozihua
 *
 */

public class RapidminerModelParser implements IModelParser {
	public static final String CMP_SUFFIX = ".cmp";
	public static final String PROP_SUFFIX = ".properties";

	private IReader modelReader;

	static {
		OperatorService.init();
		XMLImporter.init();
	}

	@Override
	public Map<String, String> parse(String arg) throws Exception {
		Map<String, String> resultMap = new HashMap<String, String>();
		// 1、通过IModelRead读取process内容
		Map<String, String> readResult = modelReader.read(arg);
		if ("exist".equals(readResult.get("status"))) {
			return readResult;
		}
		Process process = parseProcess(readResult.get("info"));
		// 2、根据解析的Process和properties生成ProcessDefinition
		ProcessDefinition pd = this.parseProcessDefinition(process, readResult);
		// 3、根据解析的Process生成com.cyberinsight.cps.cybersphere.parserengine.model.Operator
		Map<String, com.cyberinsight.cps.cybersphere.modelparser.model.Operator> operators = this.parseOperator(process,
				pd.getId());
		// 4、根据解析的Process和com.cyberinsight.cps.cybersphere.parserengine.model.Operator生成Connection
		List<Connection> connections = this.parseConnection(process, operators);
		// 5、入库
		System.out.println(pd);
		System.out.println(operators);
		System.out.println(connections);
		resultMap.put("status", "success");
		resultMap.put("info", "The zip file parsing complete");
		return resultMap;
	}

	// private String moveZipFile(String unzipFileTmpPath, Properties props)
	// throws IOException, ParseException {
	// String nameSpace = props.getProperty("namespace");
	// String name = props.getProperty("name");
	// String version = props.getProperty("version");
	// String destPath = WORK_DIR + File.separator + nameSpace + File.separator
	// + name + File.separator + version;
	//
	// if (!(StringUtils.isNotBlank(nameSpace) && StringUtils.isNotBlank(name)
	// && StringUtils.isNotBlank(version))) {
	// throw new ParseException("namespace、name、version不能为空");
	// }
	// File sourcePath = new File(unzipFileTmpPath);
	// FileUtils.moveDirectory(sourcePath, new File(destPath));
	// return destPath;
	// }

	/**
	 * 通过rapidminer引擎解析process
	 * 
	 * @param filepath
	 * @return
	 * @throws ParseException
	 */
	private Process parseProcess(String content) throws ParseException {
		Process process = null;
		try {
			process = new Process(content);
		} catch (Exception ex) {
			throw new ParseException(ex.getMessage());
		}
		return process;
	}

	/**
	 * 通过Process解析出ProcessDefinition
	 * 
	 * @param process
	 * @return
	 * @throws ParseException
	 */
	private ProcessDefinition parseProcessDefinition(Process process, Map<String, String> props) throws ParseException {
		ProcessDefinition pd = null;
		try {
			pd = new ProcessDefinition();
			ProcessRootOperator processRootOperator = process.getRootOperator();
			// 解析后参数，暂时用不上 Parameters params =
			// processRootOperator.getParameters();
			pd.setId(UUID.randomUUID().toString());
			pd.setName(processRootOperator.getName());
			pd.setVersion(process.getRootOperator().getCompatibilityLevel().toString());
			// 从文件获取
			pd.setNamespace(props.get("namespace"));
			pd.setAuthor(props.get("author"));
			pd.setCompany(props.get("company"));
			pd.setTitle(props.get("title"));
			pd.setDefinition(process.getRootOperator().getXML(true));
		} catch (Exception ex) {
			throw new ParseException(ex.getMessage());
		}
		return pd;
	}

	/**
	 * 通过Process解析出Operator
	 * 
	 * @param process
	 * @param processId
	 * @return
	 * @throws ParseException
	 */
	private Map<String, com.cyberinsight.cps.cybersphere.modelparser.model.Operator> parseOperator(Process process,
			String processId) throws ParseException {
		Map<String, com.cyberinsight.cps.cybersphere.modelparser.model.Operator> nodeMap = null;
		try {
			nodeMap = new HashMap<String, com.cyberinsight.cps.cybersphere.modelparser.model.Operator>();
			for (Operator operator : process.getRootOperator().getAllInnerOperators()) {
				Parameters params = operator.getParameters();
				com.cyberinsight.cps.cybersphere.modelparser.model.Operator node = new com.cyberinsight.cps.cybersphere.modelparser.model.Operator();
				node.setId(UUID.randomUUID().toString());
				node.setDefinition_fk(processId);
				node.setName(operator.getName());
				node.setExpanded(Boolean.valueOf(params.getParameterOrNull("expanded")));
				if (StringUtils.isNumeric(operator.getLocation().getX())) {
					node.setX(Integer.valueOf(operator.getLocation().getX()));
				}
				if (StringUtils.isNumeric(operator.getLocation().getY())) {
					node.setY(Integer.valueOf(operator.getLocation().getY()));
				}
				if (StringUtils.isNumeric(operator.getLocation().getHeight())) {
					node.setHeight(Integer.valueOf(operator.getLocation().getHeight()));
				}
				if (StringUtils.isNumeric(operator.getLocation().getWidth())) {
					node.setWidth(Integer.valueOf(operator.getLocation().getWidth()));
				}
				node.setScriptFile(params.getParameterOrNull("file"));
				node.setScriptFile(params.getParameterOrNull("method"));
				nodeMap.put(node.getName(), node);
			}
			// TODO 不知道RootOperator是否需要加入
			ProcessRootOperator processRootOperator = process.getRootOperator();
			Parameters params = processRootOperator.getParameters();
			com.cyberinsight.cps.cybersphere.modelparser.model.Operator node = new com.cyberinsight.cps.cybersphere.modelparser.model.Operator();
			node.setId(processId);
			node.setDefinition_fk(processId);
			node.setName(processRootOperator.getName());
			node.setExpanded(Boolean.valueOf(params.getParameterOrNull("expanded")));
			if (StringUtils.isNumeric(processRootOperator.getLocation().getX())) {
				node.setX(Integer.valueOf(processRootOperator.getLocation().getX()));
			}
			if (StringUtils.isNumeric(processRootOperator.getLocation().getY())) {
				node.setY(Integer.valueOf(processRootOperator.getLocation().getY()));
			}
			if (StringUtils.isNumeric(processRootOperator.getLocation().getHeight())) {
				node.setHeight(Integer.valueOf(processRootOperator.getLocation().getHeight()));
			}
			if (StringUtils.isNumeric(processRootOperator.getLocation().getWidth())) {
				node.setWidth(Integer.valueOf(processRootOperator.getLocation().getWidth()));
			}
			node.setScriptFile(params.getParameterOrNull("file"));
			node.setScriptFile(params.getParameterOrNull("method"));
			nodeMap.put(node.getName(), node);
		} catch (Exception ex) {
			throw new ParseException(ex.getMessage());
		}
		return nodeMap;
	}

	/**
	 * 通过Process解析出Connection
	 * 
	 * @param process
	 * @param nodeMap
	 * @return
	 * @throws ParseException
	 */
	private List<Connection> parseConnection(Process process,
			Map<String, com.cyberinsight.cps.cybersphere.modelparser.model.Operator> nodeMap) throws ParseException {
		List<Connection> connections = null;
		try {
			connections = new ArrayList<Connection>();
			ExecutionUnit executionUnit = process.getRootOperator().getAllInnerOperators().get(0).getExecutionUnit();
			for (OutputPort output : executionUnit.getAllOutputPorts()) {
				if (output.getDestination() != null) {
					Connection connection = new Connection();
					connection.setId(UUID.randomUUID().toString());
					OutputPort source = output.getDestination().getSource();
					// 获取from节点ID
					String from_operator_name = source.getPorts().getOwner().getOperator().getName();
					String from_operator_id = nodeMap.get(from_operator_name).getId();
					connection.setFrom_fk(from_operator_id);
					// 获取to节点ID
					String to_operator_name = source.getDestination().getPorts().getOwner().getOperator().getName();
					String to_operator_id = nodeMap.get(to_operator_name).getId();
					connection.setTo_fk(to_operator_id);
					// connection.fromName = from_operator_name;
					// connection.toName = to_operator_name;
					connections.add(connection);
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new ParseException(ex.getMessage());
		}
		return connections;
	}

	public IReader getModelReader() {
		return modelReader;
	}

	public void setModelReader(IReader modelReader) {
		this.modelReader = modelReader;
	}

}
